#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 文件名称: user_api.py
# 文件保存路径: backend/api/miniprogram/user_api.py
"""
微信小程序用户管理API
实现用户信息更新、个人资料管理等功能
"""

from flask import request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
from backend.infrastructure.database import db
from backend.models.user import User
from backend.models.student import Student  # 新增: 便于返回嵌套学生信息
from backend.api.miniprogram import miniprogram_bp
from backend.services.unified_log_service import UnifiedLogService

# 创建统一日志服务实例（仅用于通用操作日志，不误用学生档案接口）
log_service = UnifiedLogService()

@miniprogram_bp.route('/user/profile', methods=['GET'])
@jwt_required()
def get_user_profile_detail():
    """获取当前小程序用户资料（含手机号mobile用于前端展示绑定状态）

    修正说明:
    原实现未返回嵌套的 student / studentInfo 对象，只提供 student_id，
    导致前端 computeUserStatus() 无法识别已绑定学生（判定逻辑需要 student 或 studentInfo 存在）。
    现在若存在 student_id，补充完整 student 对象，并尝试附加扩展年级信息，确保与 /auth/profile 行为一致，
    解决“绑定成功但个人中心仍显示未绑定”问题。
    """
    try:
        current_user_id = get_jwt_identity()
        # get_jwt_identity 可能为字符串，转为 int 保持一致性
        try:
            current_user_id = int(str(current_user_id))
        except Exception:
            pass
        user = User.query.get(current_user_id)
        if not user:
            return jsonify({'success': False, 'message': '用户不存在'}), 404

        # 若 mobile 为空，用 username 作为回退（可能本身即手机号）
        effective_mobile = user.mobile
        try:
            if (not effective_mobile) and user.username and user.username.isdigit():
                if (len(user.username) == 11 and user.username.startswith('1')) or (6 <= len(user.username) <= 15):
                    effective_mobile = user.username
        except Exception:
            pass

        data = {
            'id': user.id,
            'username': user.username,
            'real_name': user.real_name,
            'mobile': effective_mobile,
            'email': user.email,
            'gender': user.gender,
            'birth_date': user.birth_date.isoformat() if user.birth_date else None,
            'address': user.address,
            'nickname': user.nickname,
            'avatar': user.avatar,
            'bind_status': user.bind_status,
            'student_id': user.student_id,
            'openid': user.openid
        }

        # 若已绑定学生，补充嵌套 student 对象
        if user.student_id:
            student = Student.query.get(user.student_id)
            if student:
                data['student'] = {
                    'id': student.id,
                    'name': student.name,
                    'education_id': student.education_id,
                    'school': getattr(student, 'school', None),
                    'class_name': getattr(student, 'class_name', None),
                    'gender': getattr(student, 'gender', None),
                    'parent_name': getattr(student, 'parent_name', None),
                    'parent_phone': getattr(student, 'parent_phone', None)
                }
                # 可选: 附加 StudentExtension 最新信息（保持 try 捕获，避免影响主流程）
                try:
                    from backend.models.student_extension import StudentExtension
                    latest_ext = (StudentExtension.query
                                  .filter_by(student_id=student.id)
                                  .order_by(StudentExtension.data_year.desc())
                                  .first())
                    if latest_ext:
                        data['student']['grade'] = latest_ext.grade
                        data['student']['data_year'] = latest_ext.data_year
                except Exception:
                    pass

        return jsonify({'success': True, 'data': data})
    except Exception as e:
        return jsonify({'success': False, 'message': f'获取用户资料失败: {str(e)}'}), 500

# ==================== 微信绑定接口（骨架） ====================
# 设计目标：
# 1. 前端调用 /user/wechat_bind 传入临时code，后端换取openid 并与当前用户关联。
# 2. 若openid 已绑定其他账户，返回提示避免重复绑定。
# 3. 不影响已有登录/绑定学生流程；仅追加用户与微信身份关联。
# 4. 日志纳入统一日志服务。
# 注意：实际微信API调用（code2session）需配置 appid/secret，这里保留占位。可在后续配置模块加入 WECHAT_MINIPROGRAM_CONFIG。

@miniprogram_bp.route('/user/wechat_bind', methods=['POST'])
@jwt_required()
def bind_wechat_account():
    """绑定微信openid（占位实现：未真实调用微信官方接口）"""
    try:
        current_user_id = get_jwt_identity()
        user = User.query.get(current_user_id)
        if not user:
            return jsonify({'success': False, 'message': '用户不存在'}), 404

        if user.openid:
            return jsonify({'success': False, 'message': '已绑定微信，无需重复操作'}), 400

        data = request.get_json() or {}
        code = data.get('code')
        if not code:
            return jsonify({'success': False, 'message': '缺少code参数'}), 400

        # TODO: 调用微信 jscode2session 获取 openid / session_key
        # 这里使用模拟 openid（真实实现需 requests 调用 + config 注入）
        simulated_openid = f"sim_openid_{code}"

        # 检测是否被其他账号占用
        conflict = User.query.filter_by(openid=simulated_openid).first()
        if conflict:
            return jsonify({'success': False, 'message': '该微信已绑定其他账户'}), 409

        user.openid = simulated_openid
        db.session.commit()

        # 记录用户通用操作日志
        try:
            log_service.log_operation(
                user_id=user.id,
                action='BIND_WECHAT',
                table_name='users',
                record_id=user.id,
                details='绑定微信openid'
            )
        except Exception:
            pass

        return jsonify({
            'success': True,
            'data': {'openid': user.openid},
            'message': '微信绑定成功(模拟)'
        })
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'message': f'微信绑定失败: {str(e)}'}), 500

@miniprogram_bp.route('/user/profile', methods=['PUT'])
@jwt_required()
def update_user_profile():  # 保持函数名不变，此函数无冲突
    """
    更新用户个人资料
    """
    try:
        current_user_id = get_jwt_identity()
        user = User.query.get(current_user_id)
        
        if not user:
            return jsonify({
                'success': False,
                'message': '用户不存在'
            }), 404
        
        data = request.get_json()

        # 允许更新的字段（扩展：增加 birth_date/address/nickname/avatar，并保持原字段不变）
        # 注意：若前端未传某字段则不修改，保持幂等；新增字段只追加不删除旧字段。
        allowed_fields = ['real_name', 'mobile', 'email', 'gender', 'birth_date', 'address', 'nickname', 'avatar']

        # 更新字段
        updated_fields = []
        for field in allowed_fields:
            if field in data and data[field] is not None:
                # 出生日期格式校验（简单ISO日期）
                if field == 'birth_date' and data[field]:
                    try:
                        from datetime import datetime
                        datetime.strptime(data[field], '%Y-%m-%d')
                    except ValueError:
                        return jsonify({
                            'success': False,
                            'message': '出生日期格式应为YYYY-MM-DD'
                        }), 400
                setattr(user, field, data[field])
                updated_fields.append(field)
        
        if not updated_fields:
            return jsonify({
                'success': False,
                'message': '没有需要更新的字段'
            }), 400
        
        db.session.commit()
        
        # 记录操作日志（使用通用接口，避免错误调用学生档案方法）
        try:
            log_service.log_operation(
                user_id=user.id,
                action='UPDATE_PROFILE',
                table_name='users',
                record_id=user.id,
                details=f'更新个人资料: {", ".join(updated_fields)}'
            )
        except Exception:
            pass
        
        return jsonify({
            'success': True,
            'data': {
                'updated_fields': updated_fields,
                'user_info': {
                    'real_name': user.real_name,
                    'mobile': user.mobile,
                    'email': user.email,
                    'gender': user.gender,
                    'birth_date': user.birth_date.isoformat() if user.birth_date else None,
                    'address': user.address,
                    'nickname': user.nickname,
                    'avatar': user.avatar
                }
            },
            'message': '个人资料更新成功'
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'更新个人资料失败: {str(e)}'
        }), 500

@miniprogram_bp.route('/user/password', methods=['PUT'])
@jwt_required()
def change_password():
    """
    修改密码（如果用户有密码的话）
    """
    try:
        current_user_id = get_jwt_identity()
        user = User.query.get(current_user_id)
        
        if not user:
            return jsonify({
                'success': False,
                'message': '用户不存在'
            }), 404
        
        data = request.get_json()
        old_password = data.get('old_password')
        new_password = data.get('new_password')
        
        if not all([old_password, new_password]):
            return jsonify({
                'success': False,
                'message': '缺少必要参数'
            }), 400
        
        # 验证旧密码
        if not user.verify_password(old_password):
            return jsonify({
                'success': False,
                'message': '旧密码不正确'
            }), 400
        
        # 设置新密码
        user.password = new_password
        db.session.commit()
        
        # 记录操作日志
        try:
            log_service.log_operation(
                user_id=user.id,
                action='CHANGE_PASSWORD',
                table_name='users',
                record_id=user.id,
                details='修改密码'
            )
        except Exception:
            pass
        
        return jsonify({
            'success': True,
            'message': '密码修改成功'
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': f'修改密码失败: {str(e)}'
        }), 500

@miniprogram_bp.route('/user/bind_mobile', methods=['POST'])
@jwt_required()
def bind_mobile():
    """绑定/设置手机号（占位：此处未做验证码校验，可后续扩展）"""
    try:
        current_user_id = get_jwt_identity()
        user = User.query.get(current_user_id)
        if not user:
            return jsonify({'success': False, 'message': '用户不存在'}), 404
        data = request.get_json() or {}
        mobile = data.get('mobile')
        if not mobile:
            return jsonify({'success': False, 'message': '缺少mobile'}), 400
        # 简单格式校验
        if not (len(mobile) >= 6 and mobile.isdigit()):
            return jsonify({'success': False, 'message': '手机号格式不正确'}), 400
        # 唯一占用检查（除自身外）
        conflict = User.query.filter(User.mobile == mobile, User.id != user.id).first()
        if conflict:
            return jsonify({'success': False, 'message': '该手机号已被其他账户绑定'}), 409

        user.mobile = mobile
        db.session.commit()
        try:
            log_service.log_operation(
                user_id=user.id,
                action='BIND_MOBILE',
                table_name='users',
                record_id=user.id,
                details=f'绑定手机号 {mobile}'
            )
        except Exception:
            pass
        return jsonify({'success': True, 'message': '手机号绑定成功', 'data': {'mobile': mobile}})
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'message': f'绑定手机号失败: {str(e)}'}), 500

@miniprogram_bp.route('/user/unbind_wechat', methods=['POST'])
@jwt_required()
def unbind_wechat():
    """解绑微信 openid（允许重新绑定其他微信账号）"""
    try:
        current_user_id = get_jwt_identity()
        user = User.query.get(current_user_id)
        if not user:
            return jsonify({'success': False, 'message': '用户不存在'}), 404
        if not user.openid:
            return jsonify({'success': False, 'message': '当前未绑定微信'}), 400
        user.openid = None
        db.session.commit()
        try:
            log_service.log_operation(
                user_id=user.id,
                action='UNBIND_WECHAT',
                table_name='users',
                record_id=user.id,
                details='解绑微信openid'
            )
        except Exception:
            pass
        return jsonify({'success': True, 'message': '微信解绑成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'message': f'解绑微信失败: {str(e)}'}), 500

@miniprogram_bp.route('/user/status', methods=['GET'])
@jwt_required()
def get_user_status():
    """
    获取用户状态信息
    """
    try:
        current_user_id = get_jwt_identity()
        user = User.query.get(current_user_id)
        
        if not user:
            return jsonify({
                'success': False,
                'message': '用户不存在'
            }), 404
        
        status_data = {
            'user_id': user.id,
            'username': user.username,
            'user_type': user.user_type,
            'bind_status': user.bind_status,
            'status': user.status,
            'last_login': user.last_login.isoformat() if user.last_login else None,
            'created_at': user.created_at.isoformat() if user.created_at else None,
            'has_student': bool(user.student_id)
        }
        
        return jsonify({
            'success': True,
            'data': status_data,
            'message': '获取用户状态成功'
        })
        
    except Exception as e:
        return jsonify({
            'success': False,
            'message': f'获取用户状态失败: {str(e)}'
        }), 500 